#include <iostream>
#include <vector>
#include "Thread.hpp"
#include "LockGuard.hpp"
using namespace ThreadModule;

class ThreadData
{
public:
    ThreadData(int &tickets, const std::string &name, pthread_mutex_t &mutex)
        : _tickets(tickets), _name(name), _total(0), _mutex(mutex)
    {
    }
    ~ThreadData()
    {
    }

public:
    int &_tickets; // 所有的线程，最后都会引用同一个全局的g_tickets
    std::string _name;
    int _total;
    pthread_mutex_t &_mutex;
};

// 数据不一致
int g_tickets = 10000; // 共享资源，没有保护的, 临界资源
//pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;//加锁

void route(ThreadData *td)
{
    while (true)
    {
        //加锁时让并边串行
        pthread_mutex_lock(&td->_mutex);    
        if (td->_tickets > 0) // 1
        {
            usleep(1000);
            printf("%s running, get tickets: %d\n", td->_name.c_str(), td->_tickets); // 2
            td->_tickets--;
            pthread_mutex_unlock(&td->_mutex);                                                           // 3 
            td->_total++;
        }
        else
        {
            pthread_mutex_unlock(&td->_mutex);    
            break;
        }
        // 解锁时，允许其他线程进入临界区
    }
}

void route1(ThreadData *td)
{
    while (true)
    {
        LockGuard lock(&td->_mutex);
        if (td->_tickets > 0) // 1
        {
            usleep(1000);
            printf("%s running, get tickets: %d\n", td->_name.c_str(), td->_tickets); // 2
            td->_tickets--;
            //pthread_mutex_unlock(&td->_mutex);                                                           // 3 
            td->_total++;
        }
        else
        {
            break;
        }
        // 解锁时，允许其他线程进入临界区
    }
}

const int num = 4;
int main()
{
    std::vector<Thread<ThreadData *>> threads;
    std::vector<ThreadData *> datas;
    pthread_mutex_t mutex;//加锁
    pthread_mutex_init(&mutex, nullptr);
    // 1. 创建一批线程
    for (int i = 0; i < num; i++)
    {
        std::string name = "thread-" + std::to_string(i + 1);
        ThreadData *td = new ThreadData(g_tickets, name, mutex);
        threads.emplace_back(route, td, name);
        datas.emplace_back(td);
    }

    // 2. 启动 一批线程
    for (auto &thread : threads)
    {
        //usleep(1000);
        thread.Start();
    }

    // 3. 等待一批线程
    for (auto &thread : threads)
    {
        thread.Join();
    }
    sleep(1);

    // 4. 输出统计数据
    for (auto data : datas)
    {
        std::cout << data->_name << " : " << data->_total << std::endl;
        delete data;
    }
    pthread_mutex_destroy(&mutex);
    return 0;
}

// using namespace ThreadModule;

// void print(int &cnt)
// {
//     while (cnt)
//     {
//         std::cout << "hello I am myself thread, cnt: " << cnt-- << std::endl;
//         sleep(1);
//     }
// }

// const int num = 10;

// int main()
// {
//     std::vector<Thread<int> > threads;
//     // 1. 创建一批线程
//     for (int i = 0; i < num; i++)
//     {
//         std::string name = "thread-" + std::to_string(i + 1);
//         threads.emplace_back(print, 10, name);
//     }

//     // 2. 启动 一批线程
//     for (auto &thread : threads)
//     {
//         thread.Start();
//     }

//     // 3. 等待一批线程
//     for (auto &thread : threads)
//     {
//         thread.Join();
//         std::cout << "wait thread done, thread is: " << thread.name() << std::endl;
//     }

//     // Thread<int> t1(print, 10);
//     // t1.Start();
//     // std::cout << "name: " << t1.name() << std::endl;
//     // t1.Join();
//     return 0;
// }
